/**
 * @brief timer定义
 * @version 3.0
 * @author 宋炜
 * @date 2017-2-7 ~ 2024-4-2
 * 
 * 2024-4-2  新增std::map管理的时钟结构，通常程序中启动一个和系统相关的计时器，其他的都是基于这个计时器的软计时器
 */
#pragma once

#if defined __TIMER_OLD__
#    include "timer_old.hpp"
#else
#include <functional>
#include <memory>
#include <map>
#include <list>
#include <thread>
#include <mutex>

#include "details/itimer.hpp"
#include "designM/singleton.hpp"

namespace wheels
{
class CTimer : public iTimer
{
public:

private:

private:
	std::shared_ptr< iTimer >   pt_imp__;
public:
	CTimer();
	CTimer( long ms , bool oneShot = false );
	CTimer( std::function< void () > fun , long ms , bool oneShot = false );
	CTimer( const CTimer& b ){ pt_imp__ = b.pt_imp__; }

	~CTimer();

	/**
	 * @brief 启动或者重启计时器。
	 * @param ms ， 计时时长，单位ms，当ms小于0的时候，使用就计时时长启动计时器
	 * @param oneShot ， 是否单次计时，true单次计时，否则连续计时
	 */
	virtual emErrCode Start( long ms = -1, bool oneShot = false) final;
	/**
	 * @brief 指定事件响应函数，
	 * @param fun ，事件响应的函数对象，使用std::bind完成或者直接指定函数对象
	 */
	virtual void SetOwner( std::function<void(  )> fun ) final;
	/**
	 * @brief 停止计时器
	 */
	virtual emErrCode Stop(  ) final;
	/**
	 * @brief 判断计时器是否正在运行
	 */
	virtual bool IsRuning(  ) final;

	virtual emErrCode Reset() final;

	void setTick( long tick ){ if( pt_imp__ ) { pt_imp__->setTick(tick);} }
};
 
class orderedTimer : public std::enable_shared_from_this< orderedTimer >
{
public:
	/**
	 * @brief 计时器定义
	 */
	struct stTimerItem : public std::enable_shared_from_this< stTimerItem >
	{
		uint32_t     m_id;
		uint64_t     m_abs_tick;                    // 计数数量，绝对计数数量
		uint64_t     m_rel_tick;                    // 相对计数数量
		bool         m_one_shot;
		
		mutable std::shared_ptr< orderedTimer >  pt_mgr__;     // 管理器对象
		std::function< void () >   m_cb;            // 消息通知

		stTimerItem( uint64_t t , uint32_t id , bool one_shot = false );
		stTimerItem( uint64_t t , uint32_t id , std::shared_ptr<orderedTimer> mgr, bool one_shot = false );
	        stTimerItem( const stTimerItem& b ):
		  m_id( b.m_id),
		  m_abs_tick( b.m_abs_tick ),
		  m_rel_tick( b.m_rel_tick ),
		  m_one_shot( b.m_one_shot ),
		  pt_mgr__( b.pt_mgr__ )
	        {
		    m_cb = b.m_cb;
		}
	        stTimerItem( stTimerItem&& b ):
		  m_id( b.m_id),
                  m_abs_tick( b.m_abs_tick ),
                  m_rel_tick( b.m_rel_tick ),
                  m_one_shot( b.m_one_shot )
	        {
		  pt_mgr__ = std::move( b.pt_mgr__ );
		  m_cb = std::move( b.m_cb );
		}

	  stTimerItem& operator=( const stTimerItem& b ){
	    m_id = b.m_id;
	    m_abs_tick = b.m_abs_tick;
	    m_rel_tick = b.m_rel_tick;
	    m_one_shot = b.m_rel_tick;
	    pt_mgr__ = b.pt_mgr__;
	    m_cb = b.m_cb;
	    return *this;
	  }
	  stTimerItem& operator=( stTimerItem&& b ){
	    m_id = b.m_id;
            m_abs_tick = b.m_abs_tick;
            m_rel_tick = b.m_rel_tick;
            m_one_shot = b.m_rel_tick;
            pt_mgr__ = std::move( b.pt_mgr__ );
            m_cb = std::move( b.m_cb );
	    return *this;
	  }
		/**
		 * @brief 添加回调函数操作
		 */
	        void operator()( std::function< void () > func ){ m_cb = func; }
		void on( std::function< void () > func ){ m_cb = func; }
		/**
		 * @brief 启动计时器或者关闭计时器
		 * @param sw[ I ], true 启动计时器，false关闭计时器		
		 */
		void start( bool sw );
		
	};

	friend class stTimerItem;
	
	using data_t = std::map< uint64_t , std::list< std::shared_ptr< stTimerItem > > > ;
	using iterator = data_t::iterator;
private:
	std::shared_ptr< CTimer >    pt_timer__;        // 真实的计时器
	std::atomic< uint32_t >      m_itval__;         // 滴答分度，单位ms
	std::atomic< uint64_t >      m_base_ticks__;    // 基础滴答，从对象创建开始启动，按照滴答分度计数，每次加一
	std::atomic< uint32_t >      m_base_id__;
	std::mutex                   m_mutex__;
	
	data_t                       m_data__;
private:
	/**
	 * @brief 处理系统计时器触发。触发后比对堆顶计时器，如果达到要求则触发
	 */
	void timer_processor__();
	/**
	 * @brief 启动计时器。实际是将计时器对象添加到小顶堆中进行等候处理
	 */
	void start_timer__( std::shared_ptr<stTimerItem> timer );
	void stop_timer__( std::shared_ptr<stTimerItem> timer );
public:
        orderedTimer( long itval = 1);
	~orderedTimer();
	/**
	 * @brief 创建一个计时器
	 * @param relTick
	 * @param oneShort
	 */
	std::shared_ptr< stTimerItem >
	createTimer( uint64_t relTick , bool oneShot );
	/**
	 * @brief 启动系统计时器。这个是实际计时器模块。
	 */
	void start( bool sw );

	void erase( iterator it );
	void erase( iterator b , iterator e );

	iterator begin(){ return m_data__.begin(); }
	iterator end(){ return m_data__.end(); }
};

// 实现一个单例模式的TIMER
#if !defined( SINGLETON_TIMER )
	#define SINGLETON_TIMER  1
#endif

#if SINGLETON_TIMER
	using singletonTimer = dm::singleton< orderedTimer >;
#endif
}
#endif
